home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
TECHNICA
/
COMPUTER
/
H254.ZIP
/
IRITSM3S.ZIP
/
IRIT
/
FREEFORM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-25
|
44KB
|
1,349 lines
/*****************************************************************************
* "Irit" - the 3d polygonal solid modeller. *
* *
* Written by: Gershon Elber Ver 0.2, Mar. 1990 *
******************************************************************************
* Module to provide the required interfact for the cagd library for the *
* free form surfaces and curves. *
*****************************************************************************/
#include <stdio.h>
#include <math.h>
#include "program.h"
#include "allocate.h"
#include "attribut.h"
#include "objects.h"
#include "primitiv.h"
#include "windows.h"
#include "freeform.h"
#include "graphgen.h"
static void ConvertCtlPt(ObjectStruct *PObjPt, CagdCtlPtStruct *CagdPt);
static ObjectStruct *GetControlMesh(ObjectStruct *LstObjList,
int UOrder, int VOrder,
CagdGeomType GType, char **ErrStr);
static ObjectStruct *GetControlPoly(ObjectStruct *PtObjList, int Order,
CagdGeomType GType, char **ErrStr);
static CagdRType *GetKnotVector(ObjectStruct *KntObjList, int Order,
CagdRType *KnotVector, int *Length, char **ErrStr);
static PolygonStruct *CagdPolys2IritPolys(CagdPolylineStruct *CagdPolys);
/*****************************************************************************
* Conver control point from IRIT to CAGD format. *
*****************************************************************************/
static void ConvertCtlPt(ObjectStruct *PObjPt, CagdCtlPtStruct *CagdPt)
{
int i;
CagdPointType
PtType = PObjPt -> U.CtlPt.PtType;
int PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
CagdRType
*v = PObjPt -> U.CtlPt.Coords;
CagdPt -> PtType = PtType;
if (CAGD_IS_RATIONAL_PT(PtType))
for (i = 0; i < PtSize; i++) CagdPt -> Coords[i] = *v++;
else
for (i = 1; i <= PtSize; i++) CagdPt -> Coords[i] = *++v;
}
/*****************************************************************************
* Routine to fetch the boolean object DrawCtlPt. *
*****************************************************************************/
int GetDrawCtlPt(void)
{
int DrawCtlPt;
ObjectStruct *PObj = GetObject("DRAWCTLPT");
if (PObj == NULL || !IS_NUM_OBJ(PObj)) {
WndwInputWindowPutStr("No numeric object name DRAWCTLPT is defined");
DrawCtlPt = 0;
}
else
DrawCtlPt = REAL_TO_INT(PObj -> U.R);
return DrawCtlPt;
}
/*****************************************************************************
* Routine to fetch the boolean object DrawCtlPt. *
*****************************************************************************/
int GetFourPerFlat(void)
{
int FourPerFlat;
ObjectStruct *PObj = GetObject("FLAT4PLY");
if (PObj == NULL || !IS_NUM_OBJ(PObj)) {
WndwInputWindowPutStr("No numeric object name FLAT4PLY is defined");
FourPerFlat = 0;
}
else
FourPerFlat = REAL_TO_INT(PObj -> U.R);
return FourPerFlat;
}
/*****************************************************************************
* Routine to copy the control mesh lists to the surface control mesh. *
* The surface is allocated here as well. *
* Returns the surface if o.k., otherwise NULL. *
*****************************************************************************/
static ObjectStruct *GetControlMesh(ObjectStruct *LstObjList,
int UOrder, int VOrder,
CagdGeomType GType, char **ErrStr)
{
int i, j, k, PtSize, NumVertices,
NumVerticesFirst = -1,
NumLists = 0;
CagdRType **r;
RealType *v;
ObjectStruct *SrfObj, *LstObj, *PtObj;
CagdPointType
PtType = CAGD_PT_E3_TYPE;
if (!IS_OLST_OBJ(LstObjList))
FatalError("SURFACE: Not object list object!");
while ((LstObj = LstObjList -> U.PObjList[NumLists]) != NULL &&
NumLists < MAX_OBJ_LIST) {
if (!IS_OLST_OBJ(LstObj)) {
*ErrStr = "None list object found in list";
return NULL;
}
NumVertices = 0;
while ((PtObj = LstObj -> U.PObjList[NumVertices]) != NULL &&
NumVertices < MAX_OBJ_LIST) {
if (!IS_CTLPT_OBJ(PtObj)) {
*ErrStr = "None point object found in list";
return NULL;
}
if (NumVertices++ == 0 && NumLists == 0) /* First one. */
PtType = PtObj -> U.CtlPt.PtType;
else if (PtType != PtObj -> U.CtlPt.PtType) {
*ErrStr = "Different point types found in list";
return NULL;
}
}
if (NumLists++ == 0)
NumVerticesFirst = NumVertices;
else
if (NumVerticesFirst != NumVertices) {
*ErrStr = "Different size of point lists";
return NULL;
}
}
if (NumVertices < 2 || NumLists < 2) {
*ErrStr = "Less than 2 points in a row/col";
return NULL;
}
SrfObj = GenSrfObject("", NULL, NULL);
switch (GType) {
case CAGD_SBEZIER_TYPE:
SrfObj -> U.Srf.Srf = BzrSrfNew(NumVertices, NumLists, PtType);
break;
case CAGD_SBSPLINE_TYPE:
SrfObj -> U.Srf.Srf = BspSrfNew(NumVertices, NumLists,
UOrder, VOrder, PtType);
break;
}
SetObjectColor(SrfObj, GlblPrimColor); /* Set its default color. */
PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
for (r = SrfObj -> U.Srf.Srf -> Points, i = 0; i < NumLists; i++) {
LstObj = LstObjList -> U.PObjList[i];
for (j = 0; j < NumVertices; j++) {
v = LstObj -> U.PObjList[j] -> U.CtlPt.Coords;
if (CAGD_IS_RATIONAL_PT(PtType))
for (k = 0; k < PtSize; k++) r[k][i * NumVertices + j] = *v++;
else
for (k = 1; k <= PtSize; k++) r[k][i * NumVertices + j] = *++v;
}
}
return SrfObj;
}
/*****************************************************************************
* Routine to copy the control polygon list to the curve control polygon. *
* The curve is allocated here as well. *
* Returns the curve if o.k., otherwise NULL. *
*****************************************************************************/
static ObjectStruct *GetControlPoly(ObjectStruct *PtObjList, int Order,
CagdGeomType GType, char **ErrStr)
{
int i, j, PtSize,
NumVertices = 0;
CagdRType **r;
RealType *v;
ObjectStruct *CrvObj, *PtObj;
CagdPointType
PtType = CAGD_PT_E3_TYPE;
*ErrStr = NULL;
if (!IS_OLST_OBJ(PtObjList))
FatalError("CURVE: Not object list object!");
while ((PtObj = PtObjList -> U.PObjList[NumVertices]) != NULL &&
NumVertices < MAX_OBJ_LIST) {
if (!IS_CTLPT_OBJ(PtObj))
{
*ErrStr = "None point object found in list";
return NULL;
}
if (NumVertices++ == 0) /* First one. */
PtType = PtObj -> U.CtlPt.PtType;
else if (PtType != PtObj -> U.CtlPt.PtType) {
*ErrStr = "Different point types found in list";
return NULL;
}
}
if (NumVertices < 2) {
*ErrStr = "Less than 2 points";
return NULL;
}
CrvObj = AllocObject("", CURVE_OBJ, NULL);
switch (GType) {
case CAGD_CBEZIER_TYPE:
CrvObj -> U.Crv.Crv = BzrCrvNew(NumVertices, PtType);
break;
case CAGD_CBSPLINE_TYPE:
CrvObj -> U.Crv.Crv = BspCrvNew(NumVertices, Order, PtType);
break;
}
SetObjectColor(CrvObj, GlblPrimColor); /* Set its default color. */
PtSize = CAGD_IS_RATIONAL_PT(PtType) + CAGD_NUM_OF_PT_COORD(PtType);
for (r = CrvObj -> U.Crv.Crv -> Points,i = 0; i < NumVertices; i++) {
v = PtObjList -> U.PObjList[i] -> U.CtlPt.Coords;
if (CAGD_IS_RATIONAL_PT(PtType))
for (j = 0; j < PtSize; j++) r[j][i] = *v++;
else
for (j = 1; j <= PtSize; j++) r[j][i] = *++v;
}
return CrvObj;
}
/*****************************************************************************
* Routine to copy the list of knots into the knot vector provided. *
* Returns KnotVector if o.k., NULL otherwise (sets ErrStr to description). *
* If Length == 0 it is figured from the parameters and KnotVector is *
* allocated here. *
*****************************************************************************/
static CagdRType *GetKnotVector(ObjectStruct *KntObjList, int Order,
CagdRType *KnotVector, int *Length, char **ErrStr)
{
int NumKnots = 0,
NewKnotVector = FALSE;
ObjectStruct *KntObj;
*ErrStr = NULL;
if (!IS_OLST_OBJ(KntObjList))
FatalError("KNOT: Not object list object!");
if (*Length == 0) {
while ((KntObj = KntObjList -> U.PObjList[*Length]) != NULL &&
*Length < MAX_OBJ_LIST) (*Length)++;
KnotVector = (CagdRType *) MyMalloc(sizeof(CagdRType) * *Length,
ALLOC_OTHER);
NewKnotVector = TRUE;
}
while ((KntObj = KntObjList -> U.PObjList[NumKnots]) != NULL &&
NumKnots < MAX_OBJ_LIST &&
NumKnots < *Length) {
if (!IS_NUM_OBJ(KntObj))
{
*ErrStr = "None numeric object found in list";
return NULL;
}
KnotVector[NumKnots++] = KntObj->U.R;
}
if (NumKnots == 1 && KnotVector[0] < KV_MIN_LEGAL) {
switch ((int) (KnotVector[0] - 0.5)) {
case KV_UNIFORM_OPEN:
if (NewKnotVector) {
MyFree((char *) KnotVector, ALLOC_OTHER);
KnotVector = BspKnotUniformOpen(*Length - Order, Order,
NULL);
}
else
BspKnotUniformOpen(*Length - Order, Order, KnotVector);
break;
case KV_UNIFORM_FLOAT:
if (NewKnotVector) {
MyFree((char *) KnotVector, ALLOC_OTHER);
KnotVector = BspKnotUniformFloat(*Length - Order, Order,
NULL);
}
else
BspKnotUniformFloat(*Length - Order, Order, KnotVector);
break;
default:
*ErrStr = "Invalid knot value";
fprintf(stderr,"Knot = %10.6lg (%d)",
KnotVector[0], (int) (KnotVector[0] - 0.5));
return NULL;
}
}
else if (NumKnots != *Length) {
*ErrStr = "Wrong knot vector length";
return NULL;
}
return KnotVector;
}
/*****************************************************************************
* Routine to create a Bezier surface geometric object defined by a list of *
* lists of vertices. *
*****************************************************************************/
ObjectStruct *GenBezierSurfaceObject(ObjectStruct *LstObjList)
{
char *ErrStr, Line[LINE_LEN];
ObjectStruct *SrfObj = GetControlMesh(LstObjList, -1, -1,
CAGD_SBEZIER_TYPE, &ErrStr);
if (SrfObj == NULL) {
sprintf(Line, "SBEZIER: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
}
return SrfObj;
}
/*****************************************************************************
* Routine to create a Bezier curve geometric object defined by a list of *
* vertices. *
*****************************************************************************/
ObjectStruct *GenBezierCurveObject(ObjectStruct *PtObjList)
{
char *ErrStr, Line[LINE_LEN];
ObjectStruct *CrvObj = GetControlPoly(PtObjList, -1, CAGD_CBEZIER_TYPE,
&ErrStr);
if (CrvObj == NULL) {
sprintf(Line, "CBEZIER: %s\n, empty object result.", ErrStr);
WndwInputWindowPutStr(Line);
}
return CrvObj;
}
/*****************************************************************************
* Routine to create a Bspline surface geometric object defined by a list *
* of vertices. *
*****************************************************************************/
ObjectStruct *GenBsplineSurfaceObject(RealType *RUOrder, RealType *RVOrder,
ObjectStruct *LstObjList, ObjectStruct *KntObjList)
{
int Len1, Len2,
UOrder = REAL_PTR_TO_INT(RUOrder),
VOrder = REAL_PTR_TO_INT(RVOrder);
char *ErrStr, Line[LINE_LEN];
ObjectStruct
*SrfObj = GetControlMesh(LstObjList, UOrder, VOrder,
CAGD_SBSPLINE_TYPE, &ErrStr);
if (SrfObj == NULL) {
sprintf(Line, "SBSPLINE: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
return NULL;
}
if (KntObjList -> U.PObjList[0] == NULL ||
KntObjList -> U.PObjList[1] == NULL ||
KntObjList -> U.PObjList[2] != NULL) {
WndwInputWindowPutStr("SBSPLINE: Exactly two knot vectors expected");
MyFree((char *) SrfObj, ALLOC_OBJECT);
return NULL;
}
Len1 = SrfObj->U.Srf.Srf->ULength + UOrder;
Len2 = SrfObj->U.Srf.Srf->VLength + VOrder;
if (!GetKnotVector(KntObjList -> U.PObjList[0], UOrder,
SrfObj->U.Srf.Srf->UKnotVector, &Len1, &ErrStr) ||
!GetKnotVector(KntObjList -> U.PObjList[1], VOrder,
SrfObj->U.Srf.Srf->VKnotVector, &Len2, &ErrStr)) {
sprintf(Line, "SBSPLINE: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
MyFree((char *) SrfObj, ALLOC_OBJECT);
return NULL;
}
return SrfObj;
}
/*****************************************************************************
* Routine to create a Bspline curve geometric object defined by a list of *
* vertices. *
*****************************************************************************/
ObjectStruct *GenBsplineCurveObject(RealType *ROrder, ObjectStruct *PtObjList,
ObjectStruct *KntObjList)
{
int Len,
Order = REAL_PTR_TO_INT(ROrder);
char *ErrStr, Line[LINE_LEN];
ObjectStruct
*CrvObj = GetControlPoly(PtObjList, Order, CAGD_CBSPLINE_TYPE, &ErrStr);
if (CrvObj == NULL) {
sprintf(Line, "CBSPLINE: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
return NULL;
}
if (!IS_OLST_OBJ(KntObjList))
FatalError("CBSPLINE: Knots is not object list object!");
Len = CrvObj->U.Crv.Crv->Length + Order;
if (!GetKnotVector(KntObjList, Order, CrvObj->U.Crv.Crv->KnotVector,
&Len, &ErrStr)) {
sprintf(Line, "CBSPLINE: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
MyFree((char *) CrvObj, ALLOC_OBJECT);
return NULL;
}
return CrvObj;
}
/*****************************************************************************
* Routine to subdivide a surface into two in specified direction (1 or 2) *
* and specified parameter value. *
*****************************************************************************/
ObjectStruct *DivideSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
RealType *ParamVal)
{
int Dir = REAL_PTR_TO_INT(RDir);
CagdSrfStruct
*Srf = CagdSrfSubdivAtParam(SrfObj -> U.Srf.Srf, *ParamVal, Dir);
ObjectStruct *Srf1, *Srf2, *SrfList;
if (Srf == NULL) return NULL;
Srf1 = GenSrfObject("", Srf, NULL),
SetObjectColor(Srf1, GetObjectColor(SrfObj));
Srf2 = GenSrfObject("", Srf->Pnext, NULL),
SetObjectColor(Srf2, GetObjectColor(SrfObj));
Srf -> Pnext = NULL;
SrfList = AllocObject("", OBJ_LIST_OBJ, NULL);
SrfList -> U.PObjList[0] = Srf1;
SrfList -> U.PObjList[1] = Srf2;
SrfList -> U.PObjList[2] = NULL;
return SrfList;
}
/*****************************************************************************
* Routine to extract a surface region in specified direction (1 or 2) and *
* specified parameter values. *
*****************************************************************************/
ObjectStruct *RegionFromSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
RealType *ParamVal1, RealType *ParamVal2)
{
int Dir = REAL_PTR_TO_INT(RDir);
CagdSrfStruct
*Srf = CagdSrfRegionFromSrf(SrfObj -> U.Srf.Srf,
*ParamVal1, *ParamVal2, Dir);
if (Srf == NULL) return NULL;
SrfObj = GenSrfObject("", Srf, NULL);
return SrfObj;
}
/*****************************************************************************
* Routine to subdivide a curve into two in specified parameter value. *
*****************************************************************************/
ObjectStruct *DivideCurveObject(ObjectStruct *CrvObj, RealType *ParamVal)
{
CagdCrvStruct
*Crv = CagdCrvSubdivAtParam(CrvObj -> U.Crv.Crv, *ParamVal);
ObjectStruct *Crv1, *Crv2, *CrvList;
if (Crv == NULL) return NULL;
Crv1 = GenCrvObject("", Crv, NULL),
SetObjectColor(Crv1, GetObjectColor(CrvObj));
Crv2 = GenCrvObject("", Crv->Pnext, NULL),
SetObjectColor(Crv2, GetObjectColor(CrvObj));
Crv -> Pnext = NULL;
CrvList = AllocObject("", OBJ_LIST_OBJ, NULL);
CrvList -> U.PObjList[0] = Crv1;
CrvList -> U.PObjList[1] = Crv2;
CrvList -> U.PObjList[2] = NULL;
return CrvList;
}
/*****************************************************************************
* Routine to extract a curve region in specified parameter values. *
*****************************************************************************/
ObjectStruct *RegionFromCurveObject(ObjectStruct *CrvObj,
RealType *ParamVal1, RealType *ParamVal2)
{
CagdCrvStruct
*Crv = CagdCrvRegionFromCrv(CrvObj -> U.Crv.Crv, *ParamVal1, *ParamVal2);
if (Crv == NULL) return NULL;
CrvObj = GenCrvObject("", Crv, NULL);
return CrvObj;
}
/*****************************************************************************
* Routine to refine surface in specified direction (1 or 2) and knot vector. *
* If, however, Replace is non zero, KnotsObj REPLACES current vector. *
*****************************************************************************/
ObjectStruct *RefineSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
RealType *RReplace, ObjectStruct *KnotsObj)
{
int n = 0,
Replace = REAL_PTR_TO_INT(RReplace),
Dir = REAL_PTR_TO_INT(RDir);
char *ErrStr, Line[LINE_LEN];
CagdRType
*t = GetKnotVector(KnotsObj, 0, NULL, &n, &ErrStr);
CagdSrfStruct *RefSrf;
ObjectStruct *RefSrfObj;
if (t == NULL) {
sprintf(Line, "REFINE: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
MyFree((char *) SrfObj, ALLOC_OBJECT);
return NULL;
}
RefSrf = CagdSrfRefineAtParams(SrfObj -> U.Srf.Srf, Dir, Replace, t, n);
MyFree((char *) t, ALLOC_OTHER);
if (RefSrf == NULL) return NULL;
RefSrfObj = GenSrfObject("", RefSrf, NULL),
SetObjectColor(RefSrfObj, GetObjectColor(SrfObj));
return RefSrfObj;
}
/*****************************************************************************
* Routine to refine curve in specified knot vector. *
* If, however, Replace is non zero, knotsObj REPLACES current vector. *
*****************************************************************************/
ObjectStruct *RefineCurveObject(ObjectStruct *CrvObj, RealType *RReplace,
ObjectStruct *KnotsObj)
{
int n = 0,
Replace = REAL_PTR_TO_INT(RReplace);
char *ErrStr, Line[LINE_LEN];
CagdRType
*t = GetKnotVector(KnotsObj, 0, NULL, &n, &ErrStr);
CagdCrvStruct *RefCrv;
ObjectStruct *RefCrvObj;
if (t == NULL) {
sprintf(Line, "REFINE: %s, empty object result.\n", ErrStr);
WndwInputWindowPutStr(Line);
MyFree((char *) CrvObj, ALLOC_OBJECT);
return NULL;
}
RefCrv = CagdCrvRefineAtParams(CrvObj -> U.Crv.Crv, Replace, t, n);
MyFree((char *) t, ALLOC_OTHER);
if (RefCrv == NULL) return NULL;
RefCrvObj = GenCrvObject("", RefCrv, NULL),
SetObjectColor(RefCrvObj, GetObjectColor(CrvObj));
return RefCrvObj;
}
/*****************************************************************************
* Routine to evaluate surface in specified parameter values. *
*****************************************************************************/
ObjectStruct *EvalSurfaceObject(ObjectStruct *SrfObj, RealType *u, RealType *v)
{
CagdRType *Pt = CagdSrfEval(SrfObj -> U.Srf.Srf, *u, *v);
ObjectStruct *CtlPtObj = GenCtlPtObject("", SrfObj -> U.Srf.Srf -> PType,
Pt, NULL, NULL);
return CtlPtObj;
}
/*****************************************************************************
* Routine to evaluate curve in specified parameter value. *
*****************************************************************************/
ObjectStruct *EvalCurveObject(ObjectStruct *CrvObj, RealType *t)
{
CagdRType
*Pt = CagdCrvEval(CrvObj -> U.Crv.Crv, *t);
ObjectStruct *CtlPtObj = GenCtlPtObject("", CrvObj -> U.Crv.Crv -> PType,
Pt, NULL, NULL);
return CtlPtObj;
}
/*****************************************************************************
* Routine to evaluate surface normal in specified parameter values. *
*****************************************************************************/
ObjectStruct *NormalSurfaceObject(ObjectStruct *SrfObj, RealType *u,
RealType *v)
{
int i;
RealType V[3];
CagdVecStruct
*Vec = CagdSrfNormal(SrfObj -> U.Srf.Srf, *u, *v);
ObjectStruct *NormalObj;
for (i = 0; i < 3; i++) V[i] = Vec -> Vec[i];
NormalObj = GenVecObject("", &V[0], &V[1], &V[2], NULL);
return NormalObj;
}
/*****************************************************************************
* Routine to evaluate surface tangent in specified parameter value and dir.. *
*****************************************************************************/
ObjectStruct *TangentSurfaceObject(ObjectStruct *SrfObj, RealType *RDir,
RealType *u, RealType *v)
{
int i,
Dir = REAL_PTR_TO_INT(RDir);
RealType V[3];
CagdVecStruct
*Vec = CagdSrfTangent(SrfObj -> U.Srf.Srf, *u, *v, Dir);
ObjectStruct *TangentObj;
for (i = 0; i < 3; i++) V[i] = Vec -> Vec[i];
TangentObj = GenVecObject("", &V[0], &V[1], &V[2], NULL);
return TangentObj;
}
/*****************************************************************************
* Routine to evaluate curve in specified parameter value. *
*****************************************************************************/
ObjectStruct *TangentCurveObject(ObjectStruct *CrvObj, RealType *t)
{
int i;
RealType V[3];
CagdVecStruct
*Vec = CagdCrvTangent(CrvObj -> U.Crv.Crv, *t);
ObjectStruct *TangentObj;
for (i = 0; i < 3; i++) V[i] = Vec -> Vec[i];
TangentObj = GenVecObject("", &V[0], &V[1], &V[2], NULL);
return TangentObj;
}
/*****************************************************************************
* Routine to extract an isoparametric curve out of a surface. *
*****************************************************************************/
ObjectStruct *CurveFromSurface(ObjectStruct *SrfObj, RealType *RDir,
RealType *ParamVal)
{
int Dir = REAL_PTR_TO_INT(RDir);
CagdCrvStruct
*Crv = CagdCrvFromSrf(SrfObj -> U.Srf.Srf, *ParamVal, Dir);
ObjectStruct *CrvObj;
if (Crv == NULL) return NULL;
CrvObj = GenCrvObject("", Crv, NULL);
return CrvObj;
}
/*****************************************************************************
* Routine to extract an isoparametric curve out of a surface mesh. *
*****************************************************************************/
ObjectStruct *CurveFromSrfMesh(ObjectStruct *SrfObj, RealType *RDir,
RealType *RIndex)
{
int Dir = REAL_PTR_TO_INT(RDir),
Index = REAL_PTR_TO_INT(RIndex);
CagdCrvStruct
*Crv = CagdCrvFromMesh(SrfObj -> U.Srf.Srf, Index, Dir);
ObjectStruct *CrvObj;
if (Crv == NULL) return NULL;
CrvObj = GenCrvObject("", Crv, NULL);
return CrvObj;
}
/*****************************************************************************
* Routine to reverse a curve. *
*****************************************************************************/
ObjectStruct *CurveReverse(ObjectStruct *CrvObj)
{
CagdCrvStruct
*RevCrv = CagdCrvReverse(CrvObj -> U.Crv.Crv);
if (RevCrv == NULL) return NULL;
CrvObj = GenCrvObject("", RevCrv, NULL);
return CrvObj;
}
/*****************************************************************************
* Routine to reverse a surface. *
*****************************************************************************/
ObjectStruct *SurfaceReverse(ObjectStruct *SrfObj)
{
CagdSrfStruct
*RevSrf = CagdSrfReverse(SrfObj -> U.Srf.Srf);
if (RevSrf == NULL) return NULL;
SrfObj = GenSrfObject("", RevSrf, NULL);
return SrfObj;
}
/*****************************************************************************
* Routine to convert a curve to a piecewise linear polyline approximation *
* and convert its control polygon into polyline as well. *
* Result is saved in the PLPolys/CtlPoly curve slots. *
* If however approximation alread exists, no computation is performed. *
*****************************************************************************/
void ComputeCurveIsoLines(ObjectStruct *PObj)
{
int i, j,
DrawCtlPtColor = GetDrawCtlPt(),
Resolution = GetResolution(TRUE),
RealResolution = GetResolution(FALSE);
if (!IS_CRV_OBJ(PObj))
FatalError("Curve was expected.");
if (RealResolution > 0 && PObj -> U.Crv.PLPolys == NULL) {
for (i = 1, j = Resolution; j > 0 && i < 10; i++, j >>= 1);
BzrCrvSetCache(i, TRUE);
PObj -> U.Crv.PLPolys = CagdCrv2Polyline(PObj -> U.Crv.Crv, i);
}
if (DrawCtlPtColor && PObj -> U.Crv.CtlPoly == NULL) {
PObj -> U.Crv.CtlPoly = CagdCrv2CtrlPoly(PObj -> U.Crv.Crv);
}
}
/*****************************************************************************
* Routine to convert a surface to a set of piecewise linear polylines *
* approximation and convert its control mesh into set of polyline as well. *
* Result is saved in the PLPolys/CtlMsh surface slots. *
* If however approximation alread exists, no computation is performed. *
*****************************************************************************/
void ComputeSurfaceIsoLines(ObjectStruct *PObj)
{
int i, j,
DrawCtlPtColor = GetDrawCtlPt(),
Resolution = GetResolution(TRUE),
RealResolution = GetResolution(FALSE);
if (!IS_SRF_OBJ(PObj))
FatalError("Surface was expected.");
if (RealResolution > 0 && PObj -> U.Srf.PLPolys == NULL) {
for (i = 1, j = Resolution; j > 0 && i < 10; i++, j >>= 1);
BzrCrvSetCache(i, TRUE);
PObj -> U.Srf.PLPolys = CagdSrf2Polylines(PObj -> U.Srf.Srf,
Resolution, i);
}
if (DrawCtlPtColor && PObj -> U.Srf.CtlMesh == NULL) {
PObj -> U.Srf.CtlMesh = CagdSrf2CtrlMesh(PObj -> U.Srf.Srf);
}
}
/*****************************************************************************
* Routine to convert a surface to a set of polygons approximating it. *
* Result is saved in the Polygons surface slot. *
* If however approximation alread exists, no computation is performed. *
*****************************************************************************/
void ComputeSurfacePolygons(ObjectStruct *PObj)
{
int i, j,
Resolution = GetResolution(TRUE),
FourPerFlat = GetFourPerFlat();
char
*SrfStrResolution = GetObjectStrAttrib(PObj, "resolution");
VectorType Vin;
VertexStruct *V;
PolygonStruct *P,
*PHead = NULL;
CagdPolygonStruct *CagdPoly, *CagdPolys;
if (PObj -> U.Srf.Polygons != NULL) return;
if (SrfStrResolution) {
float SrfRelResolution;
if (sscanf(SrfStrResolution, "%f", &SrfRelResolution) == 1) {
Resolution = REAL_TO_INT(Resolution * SrfRelResolution);
}
}
#ifndef __MSDOS__
/* Make the resolution more reasonable (very slow on MSDOS). */
Resolution *= 2;
#endif /* __MSDOS__ */
if (GetObjectStrAttrib(PObj, "twoperflat") != NULL)
FourPerFlat = FALSE;
if (GetObjectStrAttrib(PObj, "fourperflat") != NULL)
FourPerFlat = TRUE;
CagdPolys = CagdSrf2Polygons(PObj -> U.Srf.Srf, Resolution, TRUE,
FourPerFlat);
for (CagdPoly = CagdPolys;
CagdPoly != NULL;
CagdPoly = CagdPoly -> Pnext) {
/* All polygons are triangles! */
P = AllocPolygon(0, 0, V = AllocVertex(0, 0, NULL, NULL), NULL);
V -> Pnext = AllocVertex(0, 0, NULL, NULL); V = V -> Pnext;
V -> Pnext = AllocVertex(0, 0, NULL, NULL); V = V -> Pnext;
V -> Pnext = P -> V; /* Make the Vertex list circular. */
SET_CONVEX_POLY(P); /* Mark it as convex polygon. */
for (i = 0; i < 3; i++) { /* Convert to vertices. */
V = V -> Pnext;
for (j = 0; j < 3; j++) /* Convert to our format. */
V -> Pt[j] = CagdPoly -> Polygon[i].Pt[j];
for (j = 0; j < 3; j++)
V -> Normal[j] = CagdPoly -> Normal[i].Vec[j];
}
PT_ADD(Vin, CagdPoly -> Polygon[0].Pt, CagdPoly -> Normal[0].Vec);
UpdatePolyPlane(P, Vin); /* Update plane equation. */
P -> Pnext = PHead;
PHead = P;
}
CagdPolygonFreeList(CagdPolys);
PObj -> U.Srf.Polygons = GenPolyObject("", PHead, NULL);
SetObjectColor(PObj -> U.Srf.Polygons, GlblPrimColor);
}
/*****************************************************************************
* Routine to convert a surface/list of surfaces into set of polygons. *
*****************************************************************************/
ObjectStruct *Geometry2Polygons(ObjectStruct *Obj)
{
ObjectStruct *PObj;
if (IS_SRF_OBJ(Obj)) {
ComputeSurfacePolygons(Obj);
PObj = CopyObject(NULL, Obj -> U.Srf.Polygons, FALSE);
SetObjectColor(PObj, GlblPrimColor); /* Set its default color. */
return PObj;
}
else if (IS_OLST_OBJ(Obj))
{
int i = 0;
PolygonStruct *P;
ObjectStruct
*PObjAll = NULL;
while ((PObj = Obj -> U.PObjList[i++]) != NULL && i < MAX_OBJ_LIST) {
PObj = Geometry2Polygons(PObj);
if (PObjAll) {
if (PObj -> U.Pl.P) {
for (P = PObj -> U.Pl.P;
P -> Pnext != NULL;
P = P -> Pnext);
P -> Pnext = PObjAll -> U.Pl.P;
PObjAll -> U.Pl.P = PObj -> U.Pl.P;
PObj -> U.Pl.P = NULL;
}
MyFree((char *) PObj, ALLOC_OBJECT);
}
else {
PObjAll = PObj;
}
}
return PObjAll;
}
else {
WndwInputWindowPutStr("Unconvertable to polygons object ignored");
return NULL;
}
}
/*****************************************************************************
* Routine to convert Cagd lib polylines to Irit polylines. *
*****************************************************************************/
static PolygonStruct *CagdPolys2IritPolys(CagdPolylineStruct *CagdPolys)
{
CagdPolylineStruct *CagdPoly;
PolygonStruct
*PHead = NULL;
for (CagdPoly = CagdPolys;
CagdPoly != NULL;
CagdPoly = CagdPoly -> Pnext) {
int i, j;
VertexStruct *V;
PolygonStruct *P;
P = AllocPolygon(0, 0, V = AllocVertex(0, 0, NULL, NULL), NULL);
for (i = 0; i < CagdPoly -> Length; i++) { /* Convert to vertices. */
for (j = 0; j < 3; j++) /* Convert to our format. */
V -> Pt[j] = CagdPoly -> Polyline[i].Pt[j];
if (i < CagdPoly -> Length - 1) {
V -> Pnext = AllocVertex(0, 0, NULL, NULL);
V = V -> Pnext;
}
}
P -> Pnext = PHead;
PHead = P;
}
return PHead;
}
/*****************************************************************************
* Routine to convert a surface/curve/list of them into set of polylines. *
*****************************************************************************/
ObjectStruct *Geometry2Polylines(ObjectStruct *Obj)
{
ObjectStruct *PObj;
PolygonStruct *P, *PTail, *PHead;
int DoMeshes = GetDrawCtlPt();
if (IS_SRF_OBJ(Obj)) {
ComputeSurfaceIsoLines(Obj);
if (Obj -> U.Srf.PLPolys != NULL)
PHead = CagdPolys2IritPolys(Obj -> U.Srf.PLPolys);
else
PHead = NULL;
if (DoMeshes && Obj -> U.Srf.CtlMesh != NULL) {
P = CagdPolys2IritPolys(Obj -> U.Srf.CtlMesh);
for (PTail = P; PTail -> Pnext != NULL; PTail = PTail -> Pnext);
PTail -> Pnext = PHead;
PHead = P;
}
PObj = GenPolyObject("", PHead, NULL);
SetObjectColor(PObj, GlblPrimColor); /* Set its default color. */
SET_POLYLINE_OBJ(PObj);
return PObj;
}
if (IS_CRV_OBJ(Obj)) {
ComputeCurveIsoLines(Obj);
if (Obj -> U.Crv.PLPolys != NULL)
PHead = CagdPolys2IritPolys(Obj -> U.Srf.PLPolys);
else
PHead = NULL;
if (DoMeshes && Obj -> U.Crv.CtlPoly != NULL) {
P = CagdPolys2IritPolys(Obj -> U.Crv.CtlPoly);
for (PTail = P; PTail -> Pnext != NULL; PTail = PTail -> Pnext);
PTail -> Pnext = PHead;
PHead = P;
}
PObj = GenPolyObject("", PHead, NULL);
SetObjectColor(PObj, GlblPrimColor); /* Set its default color. */
SET_POLYLINE_OBJ(PObj);
return PObj;
}
else if (IS_OLST_OBJ(Obj))
{
int i = 0;
ObjectStruct
*PObjAll = NULL;
while ((PObj = Obj -> U.PObjList[i++]) != NULL && i < MAX_OBJ_LIST) {
PObj = Geometry2Polylines(PObj);
if (PObjAll) {
if (PObj -> U.Pl.P) {
for (P = PObj -> U.Pl.P;
P -> Pnext != NULL;
P = P -> Pnext);
P -> Pnext = PObjAll -> U.Pl.P;
PObjAll -> U.Pl.P = PObj -> U.Pl.P;
PObj -> U.Pl.P = NULL;
}
MyFree((char *) PObj, ALLOC_OBJECT);
}
else {
PObjAll = PObj;
}
}
return PObjAll;
}
else {
WndwInputWindowPutStr("Unconvertable to polylines object ignored");
return NULL;
}
}
/*****************************************************************************
* Creates a circle on the XY plane. *
*****************************************************************************/
ObjectStruct *GenCircleCurveObject(VectorType Position, RealType *Radius)
{
int i;
CagdPtStruct Pos;
CagdCrvStruct *CircCrv;
ObjectStruct *CrvObj;
for (i = 0; i < 3; i++) Pos.Pt[i] = Position[i];
CircCrv = BspCrvCreateCircle(&Pos, *Radius);
if (CircCrv == NULL) return NULL;
CrvObj = GenCrvObject("", CircCrv, NULL);
return CrvObj;
}
/*****************************************************************************
* Creates an arbitrary arc specified by Two end points and Center. Arc must *
* be less than 180 degree. *
*****************************************************************************/
ObjectStruct *GenArcCurveObject(VectorType Start, VectorType Center,
VectorType End)
{
int i;
CagdPtStruct StartPt, CenterPt, EndPt;
CagdCrvStruct *ArcCrv;
ObjectStruct *CrvObj;
for (i = 0; i < 3; i++) {
StartPt.Pt[i] = Start[i];
CenterPt.Pt[i] = Center[i];
EndPt.Pt[i] = End[i];
}
ArcCrv = BzrCrvCreateArc(&StartPt, &CenterPt, &EndPt);
if (ArcCrv == NULL) return NULL;
CrvObj = GenCrvObject("", ArcCrv, NULL);
return CrvObj;
}
/*****************************************************************************
* Construct a ruled surface out of the two provided curves. The two curves *
* must have same point type/curve type/order (and knot vector if Bspline). *
*****************************************************************************/
ObjectStruct *GenRuledSrfObject(ObjectStruct *Crv1, ObjectStruct *Crv2)
{
ObjectStruct *SrfObj;
CagdSrfStruct
*RuledSrf = CagdRuledSrf(Crv1 -> U.Crv.Crv, Crv2 -> U.Crv.Crv, 2, 2);
if (RuledSrf == NULL) return NULL;
SrfObj = GenSrfObject("", RuledSrf, NULL);
return SrfObj;
}
/*****************************************************************************
* Construct a boolean sum surface out of the four provided curves. *
*****************************************************************************/
ObjectStruct *GenBoolSumSrfObject(ObjectStruct *Crv1, ObjectStruct *Crv2,
ObjectStruct *Crv3, ObjectStruct *Crv4)
{
ObjectStruct *SrfObj;
CagdSrfStruct
*BoolSumSrf = CagdBoolSumSrf(Crv1 -> U.Crv.Crv,
Crv2 -> U.Crv.Crv,
Crv3 -> U.Crv.Crv,
Crv4 -> U.Crv.Crv);
if (BoolSumSrf == NULL) return NULL;
SrfObj = GenSrfObject("", BoolSumSrf, NULL);
return SrfObj;
}
/*****************************************************************************
* Construct a surface out of the provided curve list. *
*****************************************************************************/
ObjectStruct *GenSrfFromCrvsObject(ObjectStruct *CrvList)
{
int i,
NumCrvs = 0;
ObjectStruct *SrfObj, *CrvObj;
CagdSrfStruct *Srf;
if (!IS_OLST_OBJ(CrvList))
FatalError("SURFACE: Not object list object!");
while ((CrvObj = CrvList -> U.PObjList[NumCrvs]) != NULL &&
NumCrvs < MAX_OBJ_LIST) {
if (!IS_CRV_OBJ(CrvObj)) {
WndwInputWindowPutStr("SURFACE: List contains non curve object(s).");
return NULL;
}
if (CrvObj -> U.Crv.Crv -> Pnext != NULL) {
WndwInputWindowPutStr("SURFACE: nested curve lists are disallowed.");
return NULL;
}
NumCrvs++;
}
/* Chain all curves into a single list and invoke the srf constructor: */
for (i = 0; i < NumCrvs; i++)
CrvList -> U.PObjList[i] -> U.Crv.Crv -> Pnext =
i < NumCrvs - 1 ? CrvList -> U.PObjList[i + 1] -> U.Crv.Crv : NULL;
Srf = CagdSrfFromCrvs(CrvList -> U.PObjList[0] -> U.Crv.Crv);
for (i = 0; i < NumCrvs; i++)
CrvList -> U.PObjList[i] -> U.Crv.Crv -> Pnext = NULL;
if (Srf == NULL) return NULL;
SrfObj = GenSrfObject("", Srf, NULL);
return SrfObj;
}
/*****************************************************************************
* Construct a Sweep surface out of the CrossSection curve, Axis curve and *
* optional Scaling curve and Scaler which scales the CrossSection. *
*****************************************************************************/
ObjectStruct *GenSweepSrfObject(ObjectStruct *CrossSection, ObjectStruct *Axis,
ObjectStruct *ScalingCrv, RealType *Scale)
{
ObjectStruct *SrfObj;
CagdSrfStruct
*SweepSrf = CagdSweepSrf(CrossSection -> U.Crv.Crv, Axis -> U.Crv.Crv,
ScalingCrv ? ScalingCrv -> U.Crv.Crv : NULL, *Scale);
if (SweepSrf == NULL) return NULL;
SrfObj = GenSrfObject("", SweepSrf, NULL);
return SrfObj;
}
/*****************************************************************************
* Computes an approximation to the offset of a (planar) curve or a surface. *
*****************************************************************************/
ObjectStruct *GenOffsetObject(ObjectStruct *Obj, RealType *Offset)
{
if (IS_SRF_OBJ(Obj)) {
ObjectStruct *SrfObj;
CagdSrfStruct
*OffsetSrf = CagdSrfOffset(Obj -> U.Srf.Srf, *Offset);
if (OffsetSrf == NULL) return NULL;
SrfObj = GenSrfObject("", OffsetSrf, NULL);
return SrfObj;
}
else if (IS_CRV_OBJ(Obj)) {
ObjectStruct *CrvObj;
CagdCrvStruct
*OffsetCrv = CagdCrvOffset(Obj -> U.Crv.Crv, *Offset);
if (OffsetCrv == NULL) return NULL;
CrvObj = GenCrvObject("", OffsetCrv, NULL);
return CrvObj;
}
else {
WndwInputWindowPutStr("Offset allowed on curves/surfaces only");
return NULL;
}
}
/*****************************************************************************
* Merge two curves/ctl points into one curve by adding a linear segment *
* between the first end point to second start point. *
*****************************************************************************/
ObjectStruct *MergeCurvesAndCtlPoints(ObjectStruct *PObj1, ObjectStruct *PObj2)
{
ObjectStruct *CrvObj;
CagdCrvStruct
*Crv = NULL;
CagdPtStruct Pt1, Pt2;
if (IS_CRV_OBJ(PObj1)) {
if (IS_CRV_OBJ(PObj2)) {
Crv = CagdMergeCrvCrv(PObj1 -> U.Crv.Crv, PObj2 -> U.Crv.Crv);
}
else if (IS_CTLPT_OBJ(PObj2)) {
CagdRType
*Coords2 = PObj2 -> U.CtlPt.Coords;
CagdCoerceToE3(Pt2.Pt, &Coords2, -1, PObj2 -> U.CtlPt.PtType);
Crv = CagdMergeCrvPt(PObj1 -> U.Crv.Crv, &Pt2);
}
else
FatalError("Curve/CtlPt was expected.");
}
else if (IS_CTLPT_OBJ(PObj1)) {
CagdRType
*Coords1 = PObj1 -> U.CtlPt.Coords;
CagdCoerceToE3(Pt1.Pt, &Coords1, -1, PObj1 -> U.CtlPt.PtType);
if (IS_CRV_OBJ(PObj2)) {
Crv = CagdMergePtCrv(&Pt1, PObj2 -> U.Crv.Crv);
}
else if (IS_CTLPT_OBJ(PObj2)) {
CagdRType
*Coords2 = PObj2 -> U.CtlPt.Coords;
CagdCoerceToE3(Pt2.Pt, &Coords2, -1, PObj2 -> U.CtlPt.PtType);
Crv = CagdMergePtPt(&Pt1, &Pt2);
}
else
FatalError("Curve/CtlPt was expected.");
}
else
FatalError("Curve/CtlPt was expected.");
if (Crv == NULL) return NULL;
CrvObj = GenCrvObject("", Crv, NULL);
return CrvObj;
}
/*****************************************************************************
* Editing of a single control point of a curve. *
*****************************************************************************/
ObjectStruct *EditCrvControlPoint(ObjectStruct *PObjCrv, ObjectStruct *PObjPt,
RealType *Index)
{
ObjectStruct *CrvObj;
CagdCtlPtStruct CagdCtlPt;
CagdCrvStruct *Crv;
ConvertCtlPt(PObjPt, &CagdCtlPt);
Crv = CagdEditSingleCrvPt(PObjCrv -> U.Crv.Crv, &CagdCtlPt,
REAL_PTR_TO_INT(Index));
CrvObj = GenCrvObject("", Crv, NULL);
return CrvObj;
}
/*****************************************************************************
* Editing of a single control point of a surface. *
*****************************************************************************/
ObjectStruct *EditSrfControlPoint(ObjectStruct *PObjSrf, ObjectStruct *PObjPt,
RealType *UIndex, RealType *VIndex)
{
ObjectStruct *SrfObj;
CagdCtlPtStruct CagdCtlPt;
CagdSrfStruct *Srf;
ConvertCtlPt(PObjPt, &CagdCtlPt);
Srf = CagdEditSingleSrfPt(PObjSrf -> U.Srf.Srf, &CagdCtlPt,
REAL_PTR_TO_INT(UIndex),
REAL_PTR_TO_INT(VIndex));
SrfObj = GenSrfObject("", Srf, NULL);
return SrfObj;
}
/*****************************************************************************
* Editing of a single control point of a curve. *
*****************************************************************************/
ObjectStruct *RaiseCurveObject(ObjectStruct *PObjCrv, RealType *RNewOrder)
{
ObjectStruct *CrvObj;
CagdCrvStruct *TCrv,
*Crv = PObjCrv -> U.Crv.Crv;
int OldOrder = Crv -> Order,
NewOrder = REAL_PTR_TO_INT(RNewOrder);
if (NewOrder <= OldOrder) {
WndwInputWindowPutStr("Order to raise less the current");
return NULL;
}
while (OldOrder++ < NewOrder) {
TCrv = CagdCrvDegreeRaise(Crv);
if (Crv != PObjCrv -> U.Crv.Crv)
CagdCrvFree(Crv);
Crv = TCrv;
}
CrvObj = GenCrvObject("", Crv, NULL);
return CrvObj;
}
/*****************************************************************************
* Editing of a single control point of a curve. *
*****************************************************************************/
ObjectStruct *RaiseSurfaceObject(ObjectStruct *PObjSrf, RealType *RDir,
RealType *RNewOrder )
{
ObjectStruct *SrfObj;
CagdSrfStruct *TSrf,
*Srf = PObjSrf -> U.Srf.Srf;
int Dir = REAL_PTR_TO_INT(RDir),
OldOrder = Dir == CAGD_CONST_U_DIR ? Srf -> VOrder : Srf -> UOrder,
NewOrder = REAL_PTR_TO_INT(RNewOrder);
if (NewOrder <= OldOrder) {
WndwInputWindowPutStr("Order to raise less the current");
return NULL;
}
while (OldOrder++ < NewOrder) {
TSrf = CagdSrfDegreeRaise(Srf, Dir);
if (Srf != PObjSrf -> U.Srf.Srf)
CagdSrfFree(Srf);
Srf = TSrf;
}
SrfObj = GenSrfObject("", Srf, NULL);
return SrfObj;
}